/*
 * Compresor.h
 *
 *  Created on: 03/06/2010
 *      Author: grupo Klow
 */

#ifndef COMPRESOR_H_
#define COMPRESOR_H_

//tamanio de bloque a leer desde el archivo de entrada
#define BYTES_BLOQUE 512;


#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <map>
#include <list>
#include <fstream>
#include "Manejadores/ManejadorContexto.h"
#include "Aritmetico.h"
#include "Exclusiones.h"
#include "ConstantesCompresor.h"

typedef TTablaFreq::iterator mapIt;

class Compresor{


private:

		Aritmetico aritmetico;

		ManejadorContexto* manejador;//puntero a manejador asi es polimorfico

		map<int,int> estadisticas;//mapa con estadisticas de aciertos por orden <orden,aciertos>

		Exclusiones exclusion; //representa las exclusiones del compresor


		//FUNCIONES PRIVADAS

		/**
		 * Le retira la extension .klow al archivo pasado por parametro
		 * @return:
		 * string: nombre del archivo sin extension .klow
		 * @param:
		 * string: nombre del archivo
		 */
		string get_nombre_original(string archivo_origen);

		/**
		 * Cambia la extension del nombre pasado por parametro, o le agrega
		 * la extension .klow en caso de no tener ninguna
		 * @return:
		 * string: nombre del archivo comprimido con extension .klow
		 * @param:
		 * string: nombre del archivo a comprimir
		 */
		string get_nombre_archivo_comprimido(string archivo_origen);

		/**
		 * @return: 0 en caso de exito de apertura de archivos con exito
		 * @param:
		 * nombre del archivo: nombre de archivo a comprimir, debe tener la extension .txt
		 * file_origen:instancia de lectura del archivo
		 * file_destino:instancia de escritura del archivo
		 */
		int abrir_archivos_comprimir(string nombre_archivo,FILE ** file_origen,FILE** file_destino);

		/**
		 * @return: 0 en caso de exito de apertura de archivos con exito
		 * @param:
		 * nombre del archivo: nombre de archivo a comprimir, debe tener la extension .klow
		 * file_origen:instancia de lectura del archivo
		 * file_destino:instancia de escritura del archivo
		 */
		int abrir_archivos_descomprimir(string nombre_archivo,FILE** file_origen,FILE** file_destino,unsigned int * orden, char ** nombreArchivo);

		/**
		 * Crea una copia del contexto pasado por parametro excluyendo
		 * los caracteres excluidos por el compresor
		 * @return: copia del contexto pasado por parametro // new Contexto
		 */
		Contexto* crear_contexto_copia(Contexto* contexto_actual);

		/**
		 * Excluye del cmpresor los caracteres presentes en el contexto
		 * pasadp por parametro.
		 */
		void excluir_caracteres(Contexto* contexto);
		/**
		 * Escribe el metadata sobre el archivo pasado por parametro
		 * @parametros:
		 * file: archivo abierto para escritura
		 */
		void persistir_metadata(FILE* file,unsigned int orden, const char * nombre_archivo, unsigned int tamanioOriginal);

		void inicializar_metada(FILE * FILE,unsigned int orden, const char * nombre_archivo);

		//Obtiene el orden de un archivo comprimido y el nombre original
		void obtenerInformacionBasica(FILE * FILE,unsigned int * orden, char ** nombre_archivo);

		void actualizarContextos(int orden_actual, unsigned int orden, string cadena_contexto, TLetraExt caracter_leido);

public:

		enum Resultado_compresor {
				  OPERACION_FALLIDA_NO_ARCHIVO,
				  OPERACION_EXITOSA
		};

		/**
		 * Constructor del Compresor
		 * @param:
		 * manejador_contexto: manejador de contextos. Debe ser !=NULL
		 */
		Compresor(ManejadorContexto* manejador_contexto);

		/**
		 * Comprime el archivo de texto pasado por parametro
		 * @param:
		 * orden: orden maximo con el que trabajara la compresion
		 * archivo_origen: archivo a comprimir.
		 * @return: 0 en caso de exito o !=0 en caso de fracaso al
		 * comprimir
		 */
		 Resultado_compresor comprimir(int orden,string archivo_origen);

		/**
		 * Descomprime el archivo comprimido pasado por parametro
		 * @param:
		 * archivo_origen: archivo comprimido con extension .klow
		 * @return: 0 en caso de exito o !=0 en caso de fracaso al
		 * comprimir
		 */
		Resultado_compresor descomprimir(string archivo_origen);

		/**
		 * Muestra por std::cout las estadisticas del archivo comprimido, debe existir
		 * este archivo comprimido con extension .klow
		 * @param:
		 * archivo_origen: IMPORTANTE--> nombre del archivo original
		 */
		int imprimir_estadisticas(string archivo_origen);

};

#endif /* COMPRESOR_H_ */
